import 'package:flutter/material.dart';

class AnimatedContainerDemo extends StatefulWidget {
  AnimatedContainerDemo({Key? key}) : super(key: key);

  @override
  _AnimatedContainerDemoState createState() => _AnimatedContainerDemoState();
}

class _AnimatedContainerDemoState extends State<AnimatedContainerDemo> {
  var seeLeft = true;
  final marginTop = 30.0;
  final sideOffset = 15.0;
  final marginLR = 20.0;
  final eyeBallSize = 8.0;
  final eyeSize = 20.0;
  final eyePadding = 2.0;
  final eyeOffset = 2.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('笑嘻嘻动画'),
      ),
      body: Center(
        child: Stack(
          children: [
            ClipOval(
              child: Container(
                width: 120,
                height: 120,
                color: Colors.blue,
              ),
            ),
            Positioned(
              top: marginTop,
              left: marginLR,
              child: AnimatedContainer(
                alignment:
                    seeLeft ? Alignment.bottomLeft : Alignment.bottomRight,
                padding: EdgeInsets.all(eyePadding),
                transform: Matrix4.identity()
                  ..translate(
                      seeLeft ? 0.0 : sideOffset, seeLeft ? eyeOffset : 0.0, 0),
                duration: Duration(seconds: 1),
                curve: Curves.fastOutSlowIn,
                width: eyeSize,
                height: eyeSize,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(eyeSize / 2),
                ),
                child: ClipOval(
                  child: Container(
                    color: Colors.black,
                    width: eyeBallSize,
                    height: eyeBallSize,
                  ),
                ),
              ),
            ),
            Positioned(
              top: marginTop,
              right: marginLR,
              child: AnimatedContainer(
                alignment:
                    seeLeft ? Alignment.bottomLeft : Alignment.bottomRight,
                padding: EdgeInsets.all(eyePadding),
                transform: Matrix4.identity()
                  ..translate(seeLeft ? -sideOffset : 0.0,
                      seeLeft ? 0.0 : eyeOffset, 0),
                duration: Duration(seconds: 1),
                curve: Curves.fastOutSlowIn,
                width: eyeSize,
                height: eyeSize,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(eyeSize / 2),
                ),
                child: ClipOval(
                  child: Container(
                    color: Colors.black,
                    width: eyeBallSize,
                    height: eyeBallSize,
                  ),
                ),
              ),
            ),
            Positioned(
              bottom: 10,
              height: 40,
              left: 0,
              child: AnimatedContainer(
                alignment:
                    seeLeft ? Alignment.bottomLeft : Alignment.bottomRight,
                padding: EdgeInsets.all(4.0),
                transform: Matrix4.identity()
                  ..translate(seeLeft ? 25.0 : 35.0, 0, 0),
                duration: Duration(seconds: 1),
                curve: Curves.fastOutSlowIn,
                child: ClipPath(
                  clipper: SmileClipPath(),
                  child: Container(
                    width: 60,
                    height: 40,
                    color: Colors.yellow,
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.play_arrow, color: Colors.white),
        onPressed: () {
          setState(() {
            seeLeft = !seeLeft;
          });
        },
      ),
    );
  }
}

class SmileClipPath extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    return Path()
      ..moveTo(0, 0)
      ..arcToPoint(
        Offset(size.width, 0),
        radius: Radius.circular(size.width * 0.55),
        clockwise: false,
      )
      ..arcToPoint(
        Offset(0, 0),
        radius: Radius.circular(size.width),
        clockwise: true,
      );
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return false;
  }
}
